package indi.zhifa.recipe.bailan.framework.mysql.service.impl;

import cn.hutool.core.util.ClassUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import indi.zhifa.recipe.bailan.framework.common.entity.exception.ServiceException;
import indi.zhifa.recipe.bailan.framework.common.util.DtoEntityUtil;
import indi.zhifa.recipe.bailan.framework.mysql.entity.annotations.ZfDbService;
import indi.zhifa.recipe.bailan.framework.mysql.service.IZfDbService;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

public class ZfDbServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> implements IZfDbService<T> {

    @Override
    public <VO> Page<VO> page(IPage page, Wrapper<T> queryWrapper, Class<VO> cls) {
        IPage<T> pageData = super.page(page,queryWrapper);
        Page<VO> pageVoData = new Page<VO>(pageData.getCurrent(),pageData.getSize());
        pageVoData.setTotal(pageData.getTotal());
        pageVoData.setPages(pageData.getPages());
        List<VO> voList = DtoEntityUtil.trans(pageData.getRecords(),cls);
        pageVoData.setRecords(voList);
        return pageVoData;
    }

    @Override
    public <VO> Page<VO> page(IPage page, Wrapper<T> queryWrapper, Class<VO> cls, Function<T, VO> convertor) {
        IPage<T> pageData = super.page(page,queryWrapper);
        Page<VO> pageVoData = new Page<VO>(pageData.getCurrent(),pageData.getSize());
        pageVoData.setTotal(pageData.getTotal());
        pageVoData.setPages(pageData.getPages());
        List<VO> voList = new ArrayList<>(pageData.getRecords().size());
        for(T data : pageData.getRecords()){
            VO voData = convertor.apply(data);
            voList.add(voData);
        }
        pageVoData.setRecords(voList);
        return pageVoData;
    }

    @Override
    public <VO> List<VO> list(Wrapper<T> queryWrapper, Class<VO> cls) {
        List<T> listData = super.list(queryWrapper);
        List<VO> listVoData = DtoEntityUtil.trans(listData,cls);
        return listVoData;
    }

    @Override
    public <VO> List<VO> list(Wrapper<T> queryWrapper, Class<VO> cls, Function<T, VO> convertor) {
        List<T> listData = super.list(queryWrapper);
        List<VO> listVoData = new ArrayList<>();
        for(T data : listData){
            VO voData = convertor.apply(data);
            listVoData.add(voData);
        }
        return listVoData;
    }

    @Override
    public T findOne(Wrapper<T> queryWrapper) {
        List<T> listData = super.list(queryWrapper);
        if(CollectionUtils.isEmpty(listData)){
            return null;
        }
        return listData.get(0);
    }

    @Override
    public boolean exist(Wrapper<T> queryWrapper) {
        Long cnt = baseMapper.selectCount(queryWrapper);
        return cnt > 0;
    }

    @Override
    public T check(Serializable pId) {
        T entity = baseMapper.selectById(pId);
        if(null == entity){
            throw new ServiceException("没有找到Id为"+pId+"的"+getEntityName()+"数据");
        }
        return entity;
    }

    @Override
    public T savePull(Long pId,T pEntity) {
        boolean success = super.save(pEntity);
        if(success){
            return pEntity;
        }else{
            throw new ServiceException(getEntityName()+"存储"+pId+" 失败");
        }
    }

    @Override
    public T updatePull(Long pId, T pEntity) {
        boolean success = super.updateById(pEntity);
        if(success){
            return pEntity;
        }else {
            throw new ServiceException(getEntityName()+"更新"+pId+" 失败");
        }
    }

    @Override
    public T deleteById(Serializable pId) {
        T deletingEntity = check(pId);
        removeById(pId);
        onDelete(deletingEntity);
        return deletingEntity;
    }

    protected T onDelete(T pDeletingEntity){
        return pDeletingEntity;
    }

    protected String getEntityName(){
        ZfDbService zfDbService = this.getClass().getAnnotation(ZfDbService.class);
        if(null != zfDbService){
            return zfDbService.name();
        }else {
            return "service";
        }
    }
}
